package com.ruoyi.common.utils.generateId;

import java.util.Random;

/**
 * @Description: 获取全局唯一id
 */
public class SnowflakeIdWorker {
    //保存数字0-9 和 大小写字母
    private final String STR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private final long WORKER_ID;
    private final static long TWE_POCH = 1288834974657L;
    private long SEQUENCE = 0L;
    private final static long WORKER_ID_BITS = 4L;
    public final static long MAX_WORKER_ID = -1L ^ -1L << WORKER_ID_BITS;
    private final static long SEQUENCE_BITS = 10L;
    private final static long WORKER_ID_SHIFT = SEQUENCE_BITS;
    private final static long TIME_STAMPLEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
    public final static long SEQUENCE_MASK = -1L ^ -1L << SEQUENCE_BITS;
    private long LAST_TIMESTAMP = -1L;
    public SnowflakeIdWorker(final long workerId) {
        super();
        if (workerId > MAX_WORKER_ID || workerId < 0) {
            throw new IllegalArgumentException(String.format(
                    "worker Id can't be greater than %d or less than 0",
                    MAX_WORKER_ID));
        }
        this.WORKER_ID = workerId;
    }
    public synchronized String nextId() {
        long timestamp = this.timeGen();
        if (this.LAST_TIMESTAMP == timestamp) {
            this.SEQUENCE = (this.SEQUENCE + 1) & SEQUENCE_MASK;
            if (this.SEQUENCE == 0) {
                System.out.println("###########" + SEQUENCE_MASK);
                timestamp = this.tilNextMillis(this.LAST_TIMESTAMP);
            }
        } else {
            this.SEQUENCE = 0;
        }
        if (timestamp < this.LAST_TIMESTAMP) {
            try {
                throw new Exception(
                        String.format(
                                "Clock moved backwards. Refusing to generate id for %d milliseconds",
                                this.LAST_TIMESTAMP - timestamp));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        this.LAST_TIMESTAMP = timestamp;
        long nextId = ((timestamp - TWE_POCH << TIME_STAMPLEFT_SHIFT))
                | (this.WORKER_ID << WORKER_ID_SHIFT) | (this.SEQUENCE);
        System.out.println("timestamp:" + timestamp + ",timestampLeftShift:"
                + TIME_STAMPLEFT_SHIFT + ",nextId:" + nextId + ",workerId:"
                + WORKER_ID + ",sequence:" + SEQUENCE);
        return randomNextid(nextId);
    }

    private long tilNextMillis(final long lastTimestamp) {
        long timestamp = this.timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = this.timeGen();
        }
        return timestamp;
    }

    private long timeGen() {
        return System.currentTimeMillis();
    }

    private String randomNextid(Long nextId){
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 16; i++) {
            Random random = new Random();//创建一个新的随机数生成器
            int index = random.nextInt(STR.length());//返回[0,string.length)范围的int值    作用：保存下标
            char ch = STR.charAt(index);//charAt() : 返回指定索引处的 char 值   ==》赋值给char字符对象ch
            char id = String.valueOf(nextId).charAt(i);
            sb.append(id);
            sb.append(ch);// append(char c) :将 char 参数的字符串表示形式追加到此序列  ==》即将每次获取的ch值作拼接
        }
        return sb.toString();
    }

    /**
     * @Description: 获取唯一id
     * @param workerId 工作id
     * @return java.lang.String
     * @throws
     * @author LJY
     * @date 2019/9/21 17:10
     */
    public static String getId(String workerId){
        if(workerId == null && "".equals(workerId)){
            workerId = "2";
        }
        SnowflakeIdWorker worker = new SnowflakeIdWorker(Long.valueOf(workerId));
        return worker.nextId();
    }

    public static String leftFormatInteger(int i, int length) {
        return String.format("%0"+length+"d", i);
    }

    public static void main(String[] args){

        System.out.println(leftFormatInteger(5,5) + SnowflakeIdWorker.getId("0008"));
    }
}
